﻿using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace VietNamKey
{
    public partial class frmMain
    {
        public enum CF
        {
            Bitmap = 2,
            Dib = 8,
            Dibv5 = 0x11,
            Dif = 5,
            DspBitmap = 130,
            DspEnhMetaFile = 0x8e,
            DspMetaFilePict = 0x83,
            DspText = 0x81,
            EnhMetaFile = 14,
            GdiObjFirst = 0x300,
            GdiObjLast = 0x3ff,
            HDrop = 15,
            Locale = 0x10,
            MetaFilePict = 3,
            OemText = 7,
            OwnerDisplay = 0x80,
            Palette = 9,
            Pendata = 10,
            PrivateFirst = 0x200,
            PrivateLast = 0x2ff,
            Riff = 11,
            Sylk = 4,
            Text = 1,
            Tiff = 6,
            UnicodeText = 13,
            Wave = 12
        }

        [DllImport("user32.dll")]
        private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);

        [DllImport("User32.dll")]
        public static extern bool CloseClipboard();

        [DllImport("User32.dll")]
        public static extern bool EmptyClipboard();

        [DllImport("User32.dll")]
        public static extern IntPtr SetClipboardData(CF Format, IntPtr hMem);

        [DllImport("User32.dll")]
        public static extern bool OpenClipboard(IntPtr hWnd);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern uint SendInput(uint nInputs, INPUT64[] pInputs, int cbSize);

        private void SetClipboardAPI(string s)
        {
            OpenClipboard(IntPtr.Zero);
            EmptyClipboard();
            SetClipboardData(CF.UnicodeText, Marshal.StringToCoTaskMemUni(s));
            CloseClipboard();
        }

        private void sendAnsi(Keys k)
        {
            if (IntPtr.Size == 4)
            {
                var structure = new INPUT
                    {
                        type = 1
                    };
                structure.ki.wVk = (short) k;
                INPUT input2 = structure;
                input2.ki.dwFlags = 2;
                var pInputs = new[] {structure, input2};
                SendInput(2, pInputs, Marshal.SizeOf(structure));
            }
            else
            {
                var input3 = new INPUT64
                    {
                        type = 1
                    };
                input3.ki.wVk = (short) k;
                INPUT64 input4 = input3;
                input4.ki.dwFlags = 2;
                var inputArray2 = new[] {input3, input4};
                SendInput(2, inputArray2, Marshal.SizeOf(input3));
            }
        }

        private void sendUnicode(string s)
        {
            if (IntPtr.Size == 4)
            {
                var pInputs = new INPUT[s.Length*2];
                for (int i = 0; i < s.Length; i++)
                {
                    pInputs[i*2].type = 1;
                    pInputs[i*2].ki.wVk = 0;
                    pInputs[i*2].ki.wScan = (short) s[i];
                    pInputs[i*2].ki.dwFlags = 4;
                    pInputs[(i*2) + 1] = pInputs[i*2];
                    pInputs[(i*2) + 1].ki.dwFlags = 6;
                }
                SendInput((uint) pInputs.Length, pInputs, Marshal.SizeOf(pInputs[0]));
            }
            else
            {
                var inputArray2 = new INPUT64[s.Length*2];
                for (int j = 0; j < s.Length; j++)
                {
                    inputArray2[j*2].type = 1;
                    inputArray2[j*2].ki.wVk = 0;
                    inputArray2[j*2].ki.wScan = (short) s[j];
                    inputArray2[j*2].ki.dwFlags = 4;
                    inputArray2[(j*2) + 1] = inputArray2[j*2];
                    inputArray2[(j*2) + 1].ki.dwFlags = 6;
                }
                SendInput((uint) inputArray2.Length, inputArray2, Marshal.SizeOf(inputArray2[0]));
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct HARDWAREINPUT
        {
            public readonly int uMsg;
            public readonly short wParamL;
            public readonly short wParamH;
        }

        [StructLayout(LayoutKind.Explicit)]
        private struct INPUT
        {
            [FieldOffset(4)] public readonly HARDWAREINPUT hi;
            [FieldOffset(4)] public KEYBDINPUT ki;
            [FieldOffset(4)] public readonly MOUSEINPUT mi;
            [FieldOffset(0)] public int type;
        }

        [StructLayout(LayoutKind.Explicit)]
        private struct INPUT64
        {
            [FieldOffset(8)] public readonly HARDWAREINPUT hi;
            [FieldOffset(8)] public KEYBDINPUT ki;
            [FieldOffset(8)] public readonly MOUSEINPUT mi;
            [FieldOffset(0)] public int type;
        }

        private enum InputType
        {
            INPUT_MOUSE,
            INPUT_KEYBOARD,
            INPUT_HARDWARE
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct KEYBDINPUT
        {
            public short wVk;
            public short wScan;
            public int dwFlags;
            public readonly int time;
            public readonly IntPtr dwExtraInfo;
        }

        [Flags]
        private enum KEYEVENTF
        {
            EXTENDEDKEY = 1,
            KEYUP = 2,
            SCANCODE = 8,
            UNICODE = 4
        }

        private enum KeyModifiers : uint
        {
            Alt = 1,
            Control = 2,
            None = 0,
            Shift = 4
        }

        [Flags]
        private enum MOUSEEVENTF
        {
            ABSOLUTE = 0x8000,
            LEFTDOWN = 2,
            LEFTUP = 4,
            MIDDLEDOWN = 0x20,
            MIDDLEUP = 0x40,
            MOVE = 1,
            RIGHTDOWN = 8,
            RIGHTUP = 0x10,
            VIRTUALDESK = 0x4000,
            WHEEL = 0x800,
            XDOWN = 0x80,
            XUP = 0x100
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct MOUSEINPUT
        {
            public readonly int dx;
            public readonly int dy;
            public readonly int mouseData;
            public readonly int dwFlags;
            public readonly int time;
            public readonly IntPtr dwExtraInfo;
        }
    }
}